package cn.itsource.user.service.impl;

import cn.itsource.basic.constant.PethomeConstant;
import cn.itsource.basic.constant.VerificationConstant;
import cn.itsource.basic.exception.CustomException;
import cn.itsource.basic.utils.HttpClientUtils;
import cn.itsource.user.constant.WechatConstant;
import cn.itsource.user.domain.LoginInfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.Wechat;
import cn.itsource.user.domain.dto.LoginInfoDto;
import cn.itsource.user.mapper.LogininfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.mapper.WechatMapper;
import cn.itsource.user.service.IWechatService;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WechatServiceImpl implements IWechatService {

    @Autowired
    private WechatMapper wechatMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Map<String,Object> handleCallback(String code) {

        //获取token的url地址
        String tokenUrl = WechatConstant.TOKEN_URL.replace("APPID", WechatConstant.APPID)
                .replace("SECRET", WechatConstant.SECRET)
                .replace("CODE", code);
        //通过授权码获取token令牌
        String tokenJsonStr = HttpClientUtils.httpGet(tokenUrl);
        //把json字符串转为json对象
        JSONObject jsonObject = JSONObject.parseObject(tokenJsonStr);
        //获取token
        String access_token = jsonObject.getString("access_token");
        //微信用户唯一标志
        String openid = jsonObject.getString("openid");

        //通过token获取微信用户资源
        String userinfo_url = WechatConstant.USERINFO_URL.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
        //发送get请求
        String userinfoJsonstr = HttpClientUtils.httpGet(userinfo_url);
        //把用户信息数据转为json对象
        jsonObject = JSONObject.parseObject(userinfoJsonstr);
        //通过openid查询数据库中是否有对应的数据(注意：联表查询， t_wxuser和t_logininfo表)
        Wechat wechat = wechatMapper.loadByOpenid(openid);

        //创建一个map集合，封装数据，然后返回给前端，方便绑定微信用户
        Map<String, Object> map = new HashMap<>();

        //如果Wechat为空，就证明是第一次扫码
        if (wechat == null) {
            wechat = new Wechat();
            wechat.setOpenid(openid);
            wechat.setNickname(jsonObject.getString("nickname"));
            wechat.setSex(jsonObject.getInteger("sex"));
            wechat.setAddress(jsonObject.getString("country")+" " +
                    jsonObject.getString("province")+" "
            +jsonObject.getString("city"));
            wechat.setHeadimgurl(jsonObject.getString("headimgurl"));
            //保存微信用户基本信息
            wechatMapper.save(wechat);
            //返回某个状态，然后前端根据这个状态跳转到绑定界面
            map.put("openid", openid);
            return map;
        }else{//如果wechat不为空，就证明不是第一次扫码
            LoginInfo loginInfo = wechat.getLoginInfo();
            //如果loginInfo为空，依然跳转到绑定结买呢
            if (loginInfo == null) {
                //返回某个状态，然后前端根据这个状态跳转到绑定界面
                map.put("openid", openid);
                return map;
            }

            //loginInfo不为空，就证明是已经绑定过了，直接登录即可
            String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
            map.put("token", token);
            map.put("loginUser", loginInfo);
            return map;
        }



    }

    @Override
    public Map<String,Object> binder(LoginInfoDto loginInfoDto) throws CustomException {
        //校验数据
        checkData(loginInfoDto);
        //通过手机号码和type在t_logininfo中查询是否有数据
        LoginInfo loginInfo = logininfoMapper.loadByUsernameAndType(loginInfoDto.getPhone(), loginInfoDto.getType());
        //如果为空，就要新建账号
        if (loginInfo == null) {
            //创建LoginInfo对象
            loginInfo = createLoginInfo(loginInfoDto);
            //保存logininfo对象
            logininfoMapper.save(loginInfo);
            //创建User对象
            User user = createUser(loginInfo);
            //保存user对象
            userMapper.save(user);
        }
        //绑定微信
        wechatMapper.binder(loginInfo.getId(), loginInfoDto.getOpenid());
        //查询出来的数据为空--》添加logininfo  添加user   绑定微信用户   直接登录
        //查询出来的数据不为空---》直接绑定， 直接登录
        //一下代码就是直接在登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("loginUser", loginInfo);
        return map;

    }

    /**
     * 创建用户对象
     * @param loginInfo
     * @return
     */
    private User createUser(LoginInfo loginInfo) {
        User user = new User();
        BeanUtils.copyProperties(loginInfo,user);
        user.setState(PethomeConstant.OK);
        user.setLoginInfo(loginInfo);
        return user;
    }

    /**
     * 创建LoginInfo对象
     * @param loginInfoDto
     * @return
     */
    private LoginInfo createLoginInfo(LoginInfoDto loginInfoDto) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setPhone(loginInfoDto.getPhone());
        loginInfo.setType(loginInfoDto.getType());
        return loginInfo;
    }

    private void checkData(LoginInfoDto loginInfoDto) throws CustomException {
        if(StringUtils.isEmpty(loginInfoDto.getPhone())){
            throw new CustomException("手机号码不为空!!");
        }
        if(StringUtils.isEmpty(loginInfoDto.getCode())){
            throw new CustomException("验证码不能为空!!");
        }
        //87ui:32423424234
        String codeValue = (String) redisTemplate.opsForValue().get(loginInfoDto.getPhone() + ":" + VerificationConstant.USER_BINDER);
        if(StringUtils.isEmpty(codeValue)){
            throw new CustomException("验证码已过期!!");
        }
        if(!loginInfoDto.getCode().toUpperCase().equals(codeValue.split(":")[0].toUpperCase())){
            throw new CustomException("验证码错误!!");
        }
        if(loginInfoDto.getType()==null || StringUtils.isEmpty(loginInfoDto.getOpenid())){
            throw new CustomException("请完善基本信息!!");
        }
    }
}
